﻿#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

#endregion

namespace MetaHeuristics.Collections
{
    /// <summary>
    /// A generic 2D matrix.
    /// </summary>
    public abstract class Matrix<T> : IEnumerable<T>
    {
        private T[] values;
        private int rowCount;
        private int columnCount;


        public Matrix(int rowCount, int columnCount, T value)
        {
            this.rowCount = rowCount;
            this.columnCount = columnCount;

            this.values = new T[this.Count];
            for (int i = 0; i < rowCount * columnCount; ++i)
                this.values[i] = value;
        }

        public int RowCount
        {
            get
            {
                return rowCount;
            }
        }
        public int ColumnCount
        {
            get
            {
                return columnCount;
            }
        }

        public virtual T this[int i, int j]
        {
            get
            {
                return this.values[i * this.rowCount + j];
            }
            set
            {
                this.values[i * this.rowCount + j] = value;
            }
        }

        public virtual T this[int i]
        {
            get
            {
                return this.values[i];
            }
        }

        public int Count
        {
            get
            {
                return this.rowCount * this.columnCount;
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new TEnumerator(this.values.GetEnumerator());
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        private class TEnumerator : IEnumerator<T>
        {
            private System.Collections.IEnumerator en;
            public TEnumerator(System.Collections.IEnumerator en)
            {
                this.en = en;
            }

            public void Reset()
            {
                this.en.Reset();
            }

            public bool MoveNext()
            {
                return this.en.MoveNext();
            }

            public T Current
            {
                get
                {
                    return (T)this.en.Current;
                }
            }

            object System.Collections.IEnumerator.Current
            {
                get { return this.Current; }
            }

            void System.IDisposable.Dispose()
            {
                this.en = null;
            }
        }
    }
}
